﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

namespace DelegateByLambda
{
    public delegate void SomeDelegate(string str1, bool str2);
    //.NET 2.0中的委托引入了范型，且写法略有简化
    public delegate TResult MyFunc<T1, T2, TResult>(T1 a1, T2 a2);
    class Program
    {
        public event MyFunc<string, bool, string> MyFunc;

        public static string SomeMethod(string arg1, bool arg2)
        {
            Console.WriteLine("0");
            return arg1+",我注册了";
        }
        //在.NET 2.0中，new DelegateType已经可以省略，开发人员可以直接将方法赋值给一个委托对象的引用。当然，这个改进不值一提，C# 2.0中委托写法的关键在于引入了“匿名方法”
        //匿名方法，简单地说就是内联在方法内部的委托对象，它的关键便在于形成了一个闭包（委托执行时所需的上下文）。
        Func<int, int, int> max = (a, b) => a > b ? a : b;
        public static void TestRequest(string url)
        {
            WebRequest request = HttpWebRequest.Create(url);
            request.BeginGetResponse(delegate(IAsyncResult ar)
            {
                using (WebResponse response = request.EndGetResponse(ar))
                {
                    Console.WriteLine("{0}: {1}", url, response.ContentLength);
                }
            },
            null);
        }
        //3.5引入Lambda
        //Lambda表达式在C#中的写法是“arg-list => expr-body”，“=>”符号左边为表达式的参数列表，右边则是表达式体（body）。参数列表可以包含0到多个参数，参数之间使用逗号分割
        public static void TestRequestByLambda(string url)
        {
            WebRequest webRequest = HttpWebRequest.Create(url);
            webRequest.BeginGetResponse(ar => TestAsyncCallback(ar, webRequest, url),null);

        }
        public static void TestAsyncCallback(IAsyncResult ar, WebRequest request, string url)
        {
            using (WebResponse response = request.EndGetResponse(ar))
            {
                Console.WriteLine("{0}: {1}", url, response.ContentLength);
            }
        }
        //private Lazy<SomeClass> m_lazyInstance = new Lazy<SomeClass>(delegate { return new SomeClass(); });

        //public SomeClass Instance { get { return this.m_lazyInstance.Value; } }
        private Lazy<SomeClass> m_lazyInstance =
    new Lazy<SomeClass>(() => new SomeClass());
        public SomeClass Instance { get { return this.m_lazyInstance.Value; } }

        protected string DoSomeMethed(string arg1, bool arg2)
        {
            var handler = MyFunc;
            if (handler != null)
            {
                return handler(arg1, arg2);
            }
            return "没有注册";
        }

        static void Main(string[] args)
        {

            //在.NET 1.x中需要使用new DelegateType(...)的方式来创建一个委托对象。不过，作为委托对象内部的方法它既可以是实例方法，也可以是静态方法。
            //此外，方法只需要匹配委托类型的签名和返回值即可，方法参数的名称不会成为约束
            SomeClass someClass = new SomeClass();
            SomeDelegate someDelegate = new SomeDelegate(someClass.SomeMethod);
            someClass.SomeEvent += new SomeDelegate(someClass.SomeMethod);
            someClass.OnEvent();
            Program program = new Program();
            program.MyFunc += SomeMethod;
            string msg = program.DoSomeMethed("15", true);
            Console.WriteLine(msg);
            Console.ReadLine();

        }
    }
    public class SomeClass
    {
        public void SomeMethod(string a1, bool a2) { Console.WriteLine("1"); }

        public event SomeDelegate SomeEvent;

        public void OnEvent()
        {
            var handler = SomeEvent;
            if (handler != null)
                handler("sa", true);
        }

        //private object m_mutex = new object();
        //private bool m_initialized = false;
        //private SomeClass m_instance = null;
        //public SomeClass Instance
        //{
        //    get
        //    {
        //        if (!this.m_initialized)
        //        {
        //            lock (this.m_mutex)
        //            {
        //                if (!this.m_initialized)
        //                {
        //                    this.m_instance = new SomeClass();
        //                    this.m_initialized = true;
        //                }
        //            }
        //        }

        //        return this.m_instance;
        //    }
        //}
        //输入一个表示整型的字符串列表，并返回一个列表，包含其中偶数的平方，并且需要按照平方后的结果排序
        static List<int> GetSquaresOfPositive(List<string> strList)
        {
            List<int> intList = new List<int>();
            //foreach (var s in strList) intList.Add(Int32.Parse(s));
            List<int> evenList = new List<int>();
            intList = strList.ConvertAll<int>(i=>int.Parse(i));
  
            foreach (int i in intList)
            {
                if (i % 2 == 0) evenList.Add(i);
            }

            List<int> squareList = new List<int>();
            foreach (int i in evenList) squareList.Add(i * i);

            squareList.Sort();
            //以上需求可通过lamda一个语句搞定
            //intList = strList.SelectMany((i) =>
            //{
            //    int value = int.Parse(i);
            //    List<int> eList = new List<int>();
            //    if (value % 2 == 0) eList.Add(value * value);
            //    eList.Sort();
            //    return eList;
            //}).ToList();
            
            return squareList;
        }
        static List<int> GetSquaresOfPositiveByLambda(List<string> strList)
        {
            return strList
                .Select(s => Int32.Parse(s)) // 转成整数
                .Where(i => i % 2 == 0) // 找出所有偶数
                .Select(i => i * i) // 算出每个数的平方
                .OrderBy(i => i) // 按照元素自身排序
                .ToList(); // 构造一个List
        }
        //列出所有的关键字，根据其首字母进行分组，并且要求对每组内部的关键字进行排序
        static Dictionary<char, List<string>> GetIndex(IEnumerable<string> keywords)
        {
            // 定义字典
            var result = new Dictionary<char, List<string>>();

            // 填充字典
            foreach (var kw in keywords)
            {
                var firstChar = kw[0];
                List<string> groupKeywords;
                //TryGetValue 获取指定key的value 
                //如果未找到键，value 参数便为值类型 TValue 获取适当的默认值；例如，为 integer 类型获取 0（零），为布尔值类型获取 false，为引用类型获取 null。
                if (!result.TryGetValue(firstChar, out groupKeywords))
                {
                    groupKeywords = new List<string>();
                    result.Add(firstChar, groupKeywords);
                }

                groupKeywords.Add(kw);
            }

            // 为每个分组排序
            foreach (var groupKeywords in result.Values)
            {
                groupKeywords.Sort();
            }

            return result;
        }
        static Dictionary<char,List<string>> GetIndexByLambda(IEnumerable<string> keywords)
        {
            return keywords.GroupBy(k => k[0])
                .ToDictionary(
                g => g.Key,
                g => g.OrderBy(k => k).ToList());
        }




    }

    public class Lazy<T>
    {
        public Lazy(Func<T> func)
        {
            this.m_initialized = false;
            this.m_func = func;
            this.m_mutex = new object();
        }

        private Func<T> m_func;

        private bool m_initialized;
        private object m_mutex;
        private T m_value;

        public T Value
        {
            get
            {
                if (!this.m_initialized)
                {
                    lock (this.m_mutex)
                    {
                        if (!this.m_initialized)
                        {
                            this.m_value = this.m_func();
                            this.m_func = null;
                            this.m_initialized = true;
                        }
                    }
                }

                return this.m_value;
            }
        }
    }

}
